#
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
#
# Licensed to you under the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  See the files README and
# LICENSE_GPL_v2 which accompany this distribution.
#

import unittest as ut
import time

import basicVdsTest as vdst
import vdsClient as vdsc

DISCONNECTSP_RUTHRC_SAMPLE = """
[disconnectsp]

#
# MANDATORY options
#
server1 = server:/export/dir1
server2 = server:/export/dir2

# OPTIONAL, well, options
#domain1 =
#domain2 =
#domain3 =
#pool1 =
#pool2 =
#hostid =
#pool1key =
#pool2key =

#tasktimeout =

#image1
#parent1
#child11 .. child13

#image2
#parent2
#child21 .. child26

#image3
#parent3
#child31 .. child36

#descrption =
#vm =
#autoclean = True
"""

class Failure(Exception):
    reason = ""
    def __init__(self, arg, resp):
        self.arg = arg
        self.cmd = " ".join([str(i) for i in self.arg])
        self.resp = resp
        self.reason = self.resp['status']['message']

def validateConfig(cfg):
    '''Validate configuration "cfg" (ConfigParser) to be complete and coherent
    '''
    valid, reason = False, "Configuration is incomplete"
    if cfg.has_section('disconnectsp'):
        if (cfg.has_option('disconnectsp', 'server1') and
            cfg.has_option('disconnectsp', 'server2')):
            valid = True
            reason = "Configuration is correct and sane"
        else:
            valid, reason = False, "At least two NFS servers must be defined"

        if not cfg.has_option('disconnectsp', 'domain1'):
            cfg.set('disconnectsp', 'domain1', vdsc.VDSClient.newUUID())

        if not cfg.has_option('disconnectsp', 'domain2'):
            cfg.set('disconnectsp', 'domain2', vdsc.VDSClient.newUUID())

        if not cfg.has_option('disconnectsp', 'domain3'):
            cfg.set('disconnectsp', 'domain3', vdsc.VDSClient.newUUID())

        if not cfg.has_option('disconnectsp', 'pool1'):
            cfg.set('disconnectsp', 'pool1', vdsc.VDSClient.newUUID())

        if not cfg.has_option('disconnectsp', 'hostid'):
            cfg.set('disconnectsp', 'hostid', '7')

        if not cfg.has_option('disconnectsp', 'pool1key'):
            cfg.set('disconnectsp', 'pool1key', "NFSKEY")

        if not cfg.has_option('disconnectsp', 'tasktimeout'):
            cfg.set('disconnectsp', 'tasktimeout', '60')


        if not cfg.has_option('disconnectsp', 'autoclean'):
            cfg.set('disconnectsp', 'autoclean', 'True')

    return valid, reason


class disconnectSP(vdst.BasicVDSTest):
    '''
    disconnectStoragePool verifies disconnection of the freshly created pool.
    '''
    @classmethod
    def tests(cls):
        return [
            "disconnectSP",
            ]

    def wrap(self, *args, **kwargs):
        f = getattr(self, args[0])
        resp = f(*args[1:], **kwargs)
        if not resp['status']['code'] == 0:
            raise Failure(args, resp)
        return resp


    def setUp(self):
        # Access to configuration available via self.cfg
        self.debug = self.cfg.getboolean('disconnectsp', 'debug')

        self.server1 = self.cfg.get('disconnectsp', 'server1')
        self.server2 = self.cfg.get('disconnectsp', 'server2')

        self.sdUUID1 = self.cfg.get('disconnectsp', 'domain1')
        self.sdUUID2 = self.cfg.get('disconnectsp', 'domain2')
        self.sdUUID3 = self.cfg.get('disconnectsp', 'domain3')

        self.spUUID1 = self.cfg.get('disconnectsp', 'pool1')
        self.hostid  = self.cfg.get('disconnectsp', 'hostid')
        self.pool1key = self.cfg.get('disconnectsp', 'pool1key')

        self.timeout = self.cfg.getint('disconnectsp', 'tasktimeout')

        self.autoclean = self.cfg.getboolean('disconnectsp', 'autoclean')

        self.nfsConList = [
            {'id':1, 'connection':self.server1},
            {'id':2, 'connection':self.server2},
        ]

        vdst.BasicVDSTest.setUp(self)

        # Make sure there are no previous pool connected
        resp = self.getConnectedStoragePoolsList()

        assert (resp['status']['code'] == 0)
        if len(resp['poollist']) != 0:
            raise Exception("vdsm is connected to a pool, cannot proceede")

        # Connect storage
        self.connectStorageServer(vdsc.NFS_SERVER_TYPE, self.nfsConList)

    def tearDown(self):
        # Cleanup everything that may be left behind

        if self.autoclean:
            if self.debug:
                print "Cleaning up after the disconnectsp run"
            for domain in [self.sdUUID1, self.sdUUID2]:
                if self.debug:
                    print "Cleaning up SD", domain
                s, resp = self.formatStorageDomain(domain)

            if self.debug:
                print "Disconnecting storage"
            s, resp = self.disconnectStorageServer(vdsc.NFS_SERVER_TYPE,
                self.nfsConList)

        vdst.BasicVDSTest.tearDown(self)


    def runDisconnectSPFlow(self):
        '''Run the full disconnectsp flow
        '''
        print "Creating Storage Domain 1", self.sdUUID1
        self.wrap("createStorageDomain", vdsc.NFS_SERVER_TYPE, self.sdUUID1,
            "Storage Domain 1", self.server1, vdsc.DATA_CLASS)

        print "Creating Storage Domain 2", self.sdUUID2
        self.wrap("createStorageDomain", vdsc.NFS_SERVER_TYPE, self.sdUUID2,
            "Storage Domain 2", self.server2, vdsc.DATA_CLASS)

        print "Creating Storage Pool 1", self.spUUID1
        self.wrap("createStoragePool", self.spUUID1, "Storage Pool 1",
            self.sdUUID1, [self.sdUUID1, self.sdUUID2], 1)

        print "Connecting to Pool 1", self.spUUID1
        self.wrap("connectStoragePool", self.spUUID1, self.hostid, self.pool1key)

        print "Getting info on Pool 1", self.spUUID1
        resp = self.wrap("getStoragePoolInfo", self.spUUID1)

        print resp

        print "Disconnecting from Pool 1", self.spUUID1
        self.wrap("disconnectStoragePool", self.spUUID1, self.hostid, self.pool1key)

#        print "Making sure SPM status is free"
#        resp = self.wrap("getSpmStatus", self.spUUID1)
#
#        self.assertEqual(resp['spm_st']['spmStatus'], 'Free',
#            "SPM status is not 'Free'")
#
#        spmId = resp['spm_st']['spmId']
#        spmLver = resp['spm_st']['spmLver']
#
#        print "Making sure SPM rejects bogus spmId/spmlVer (999999/999999)...",
#        resp = self.wrap("spmStart", self.spUUID1, 999999, 999999, 0, False)
#        print "rejected"
#
#        taskId = resp['uuid']
#
#        self.assertRaises(vdsc.TaskFailed, self.waitForTask, taskId, self.timeout)
#
#        print "Trying to start SPM...",
#        resp = self.wrap("spmStart", self.spUUID1, spmId, spmLver, 0, False)
#        taskId = resp['uuid']
#        resp = self.waitForTask(taskId, self.timeout)
#        self.assertEqual(resp['taskStatus']['taskResult'], 'success')
#        print "started"
#
#        print "Activate Storage Domain 1", self.sdUUID1
#        self.wrap("activateStorageDomain", self.sdUUID1, self.spUUID1)
#
#        print "Activate Storage Domain 2", self.sdUUID2
#        self.wrap("activateStorageDomain", self.sdUUID2, self.spUUID1)

#        print "Destroying Storage Pool 1", self.spUUID1
#        self.wrap("destroyStoragePool", self.spUUID1, self.hostid, self.pool1key)

#        print "Disconnecting from Pool 1", self.spUUID1
#        self.wrap("disconnectStoragePool", self.spUUID1, self.hostid, self.pool1key)

#        print "Formatting Storage Domain 3", self.sdUUID3
#        self.wrap("formatStorageDomain", self.sdUUID3)
#
#        print "Formatting Storage Domain 2", self.sdUUID2
#        self.wrap("formatStorageDomain", self.sdUUID2)
#
#        print "Formatting Storage Domain 1", self.sdUUID1
#        self.wrap("formatStorageDomain", self.sdUUID1)

    def disconnectSP(self):
        '''disconnectStoragePool flow test'''

        try:
            # Run tests
            self.runDisconnectSPFlow()

        except Failure, e:
            print "Failed command '%s'" % e.cmd
            self.assertTrue(False, e.reason)


def suite():
    # Load everything works like that:
    # basicsuite = ut.TestLoader().loadTestsFromTestCase(TemplateTest)
    # Combine suites like that:
    # suite = ut.TestSuite([suite1, suite2, suite3])

    suite = ut.TestSuite(map(disconnectSP, disconnectSP.tests()))

    return suite
